package com.kim.androidbase.packageinfo;

import java.io.ByteArrayInputStream;
import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateFactory;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.pm.Signature;

public class PackageUtils {

	private static PackageUtils instance;

	private PackageManager packageManager;
	private Context context;

	private PackageUtils(Context context) {
		this.context = context;
	}

	public static PackageUtils getInstance(Context context) {
		if (instance == null) {
			instance = new PackageUtils(context);
			instance.getPackageManager();
		}
		return instance;
	}

	/**
	 * 获取包管理器
	 * 
	 * @return
	 */
	public PackageManager getPackageManager() {
		if (packageManager == null) {
			packageManager = context.getPackageManager();
		}
		return packageManager;
	}

	/**
	 * 获取包信息
	 * 
	 * @param packageName
	 * @param flags
	 * @return
	 * @throws NameNotFoundException
	 */
	public PackageInfo getPackageInfo(String packageName, int flags)
			throws NameNotFoundException {
		return packageManager.getPackageInfo(packageName, flags);
	}

	/**
	 * 获取应用信息
	 * 
	 * @param packageName
	 * @param flags
	 * @return
	 * @throws NameNotFoundException
	 */
	public ApplicationInfo getApplicationInfo(String packageName, int flags)
			throws NameNotFoundException {
		return packageManager.getApplicationInfo(packageName, flags);
	}

	/**
	 * 获取apk安装包信息
	 * 
	 * @param archiveFilePath
	 * @return
	 */
	public PackageInfo getUninstalledPackageInfo(String archiveFilePath) {
		return getPackageManager().getPackageArchiveInfo(archiveFilePath,
				PackageManager.GET_ACTIVITIES);
	}

	/**
	 * 获取全部已安装应用信息
	 * 
	 * @return
	 */
	public List<ResolveInfo> getAllInstalledApplications() {
		Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
		mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
		return packageManager.queryIntentActivities(mainIntent, 0);
	}

	/**
	 * 判断应用示范已安装
	 * 
	 * @param packageInfo
	 * @return
	 */
	public boolean isInstalled(PackageInfo packageInfo) {
		if (packageInfo == null || packageInfo.packageName == null) {
			return false;
		}
		List<ResolveInfo> installedApps = getAllInstalledApplications();
		for (ResolveInfo resolveInfo : installedApps) {
			if (resolveInfo == null || resolveInfo.resolvePackageName == null) {
				continue;
			}
			if (resolveInfo.resolvePackageName.equals(packageInfo.packageName)) {
				return true;
			}
		}
		return false;
	}

	public Map<String, String> getSignatureInfo(PackageInfo packageInfo) {
		if (packageInfo == null) {
			return null;
		}
		Signature[] signatures = packageInfo.signatures;
		if (signatures == null || signatures.length == 0) {
			return null;
		}
		return parseSignature(signatures[0].toByteArray());
	}

	private HashMap<String, String> parseSignature(byte[] signature) {
		try {
			CertificateFactory certFactory = CertificateFactory
					.getInstance("X.509");
			X509Certificate cert = (X509Certificate) certFactory
					.generateCertificate(new ByteArrayInputStream(signature));
			String pubKey = cert.getPublicKey().toString();
			String signNumber = cert.getSerialNumber().toString();
			System.out.println("signName:" + cert.getSigAlgName());
			System.out.println("pubKey:" + pubKey);
			System.out.println("signNumber:" + signNumber);
			System.out.println("subjectDN:" + cert.getSubjectDN().toString());
			System.out.println("signatureInfoStr:" + cert.toString());

			HashMap<String, String> signatureInfo = new HashMap<String, String>();

			int isExpired = 0;
			try {
				cert.checkValidity();
			} catch (Exception e) {
				if (e instanceof CertificateExpiredException) {
					isExpired = 1;
				} else if (e instanceof CertificateNotYetValidException) {
					isExpired = 2;
				}
			}

			signatureInfo.put("", isExpired + "");
			signatureInfo.put("signName", cert.getSigAlgName());
			signatureInfo.put("pubKey", cert.getPublicKey().toString());
			signatureInfo.put("signNumber", cert.getSerialNumber().toString());
			signatureInfo.put("subjectDN", cert.getSubjectDN().toString());
			signatureInfo.put("signatureInfoStr", cert.toString());

			return signatureInfo;
		} catch (CertificateException e) {
			e.printStackTrace();
		}
		return null;
	}
}
